home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / MSC2BC.ARJ / BGIGRF.C < prev    next >
C/C++ Source or Header  |  1991-12-05  |  35KB  |  1,195 lines

  1. /*
  2.    GRAPHICS DEMO FOR Borland C++ 3.0 graphics.h
  3.    Produces results comparable to those from MSCGRF.C
  4.  
  5.    Copyright (c) 1987,88,91 Borland International. All rights reserved.
  6.  
  7.    From the command line, use:
  8.  
  9.         bcc bgidemo.c graphics.lib
  10.  
  11. */
  12.  
  13. #ifdef __TINY__
  14. #error BGIDEMO will not run in the tiny model.
  15. #endif
  16.  
  17. #include <dos.h>
  18. #include <math.h>
  19. #include <conio.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <stdarg.h>
  23.  
  24. #include <graphics.h>
  25.  
  26. /* Note 1 - borlandc builds in the random function, and defines RAND_MAX as
  27.    unsigned.
  28. */
  29. /* torad converts degrees to radians */
  30. #define torad( d )    (( (double)(d) * PI ) / 180.0 )
  31.  
  32. /* Note 2 - FONT_PATH is the location of the .CHR files used by this program.
  33.    Edit it as appropriate for your environment.
  34. */
  35. #define FONT_PATH "H:\\BCPP3\\BGI"
  36.  
  37. /* Note 3 - COLORS, HORIZ_DIR, VERT_DIR, FILLS, predefined fill patterns,
  38.    viewporttype, and SOLID_STYLE  are defined in graphics.h.
  39.  */
  40.  
  41. #define ESC    0x1b            /* Define the escape key    */
  42. #define TRUE    1            /* Define some handy constants    */
  43. #define FALSE    0            /* Define some handy constants    */
  44. #define PI    3.14159         /* Define a value for PI    */
  45. #define ON    1            /* Define some handy constants    */
  46. #define OFF    0            /* Define some handy constants    */
  47.  
  48. /* Note 4 - Information about the BGI .CHR font files is defined below.
  49.  */
  50. #define NFONTS BOLD_FONT+1
  51.  
  52. char *Fonts[NFONTS] =
  53. {
  54.   "DefaultFont",   "TriplexFont",   "SmallFont",
  55.   "SansSerifFont", "GothicFont", "ScriptFont", "SimplexFont",
  56.   "TriplexScriptFont", "ComplexFont", "EuropeanFont", "BoldFont"
  57. };
  58.  
  59. /* Note 5 - Borland C++ has no built-in data about shape fill styles,
  60.    line drawing styles, and text justification.
  61. */
  62. char *LineStyles[] =
  63. {
  64.   "SolidLn",  "DottedLn",  "CenterLn",  "DashedLn",  "UserBitLn"
  65. };
  66.  
  67. char *FillStyles[] =
  68. {
  69.   "EmptyFill",  "SolidFill",      "LineFill",      "LtSlashFill",
  70.   "SlashFill",  "BkSlashFill",    "LtBkSlashFill", "HatchFill",
  71.   "XHatchFill", "InterleaveFill", "WideDotFill",   "CloseDotFill"
  72. };
  73.  
  74. char *TextDirect[] =
  75. {
  76.   "HorizDir",  "VertDir"
  77. };
  78.  
  79. char *HorizJust[] =
  80. {
  81.   "LeftText",   "CenterText",   "RightText"
  82. };
  83.  
  84. char *VertJust[] =
  85. {
  86.   "BottomText",  "CenterText",  "TopText"
  87. };
  88.  
  89. struct PTS
  90. {
  91.   int x, y;
  92. };    /* Structure to hold vertex points    */
  93.  
  94. /* Note 6 - The Borland C++ initgraph function initializes the graphics
  95.    system, loading the appropriate BGI driver.    The global variables below
  96.    contain information about the state of the BGI graphics system.
  97. */
  98. int    GraphDriver;        /* The Graphics device driver        */
  99. int    GraphMode;        /* The Graphics mode value        */
  100. double AspectRatio;        /* Aspect ratio of a pixel on the screen*/
  101. int    MaxX, MaxY;        /* The maximum resolution of the screen */
  102. int    MaxColors;        /* The maximum # of colors available    */
  103. int    ErrorCode;        /* Reports any graphics errors        */
  104. struct palettetype palette;        /* Used to read palette info    */
  105.  
  106. /*                                    */
  107. /*    Function prototypes                        */
  108. /*                                    */
  109.  
  110. void Initialize(void);
  111. void ReportStatus(void);
  112. void TextDump(void);
  113. void RandomBars(void);
  114. void TextDemo(void);
  115. void ColorDemo(void);
  116. void ArcDemo(void);
  117. void CircleDemo(void);
  118. void PieDemo(void);
  119. void BarDemo(void);
  120. void PutPixelDemo(void);
  121. void PutImageDemo(void);
  122. void LineToDemo(void);
  123. void CRTModeDemo(void);
  124. void UserLineStyleDemo(void);
  125. void FillStyleDemo(void);
  126. void PaletteDemo(void);
  127. void PolyDemo(void);
  128. void SayGoodbye(void);
  129. void Pause(void);
  130. void MainWindow(char *header);
  131. void StatusLine(char *msg);
  132. void DrawBorder(void);
  133. void changetextstyle(int font, int direction, int charsize);
  134. int  gprintf(int *xloc, int *yloc, char *fmt, ... );
  135. /* Note 7 - Borland C++ has a built-in delay function in dos.h. */
  136.  
  137. /*                                    */
  138. /*    Begin main function                        */
  139. /*                                    */
  140.  
  141. int main()
  142. {
  143.  
  144.   Initialize();         /* Set system into Graphics mode    */
  145.   ReportStatus();        /* Report results of the initialization */
  146.  
  147.   ColorDemo();            /* Begin actual demonstration        */
  148.   if( GraphDriver==EGA || GraphDriver==EGALO || GraphDriver==VGA )
  149.     PaletteDemo();
  150.   PutPixelDemo();
  151.   PutImageDemo();
  152.   BarDemo();
  153.   RandomBars();
  154.   ArcDemo();
  155.   CircleDemo();
  156.   PieDemo();
  157.   LineToDemo();
  158.   UserLineStyleDemo();
  159.   TextDump();
  160.   TextDemo();
  161.   CRTModeDemo();
  162.   FillStyleDemo();
  163.   PolyDemo();
  164.   SayGoodbye();         /* Give user the closing screen     */
  165.  
  166.   /* Note 8 - Close the BGI system, resetting the graphics adapter to text
  167.      mode before exiting from a Borland C++ graphics program.
  168.    */
  169.   closegraph();         /* Return the system to text mode    */
  170.   return(0);
  171. }
  172.  
  173. /*                                    */
  174. /* Note 9 - INITIALIZE: Initializes the graphics system and reports    */
  175. /*        any errors which occured.                    */
  176. /*                                    */
  177.  
  178. void Initialize(void)
  179. {
  180.   int xasp, yasp;            /* Used to read the aspect ratio*/
  181.  
  182.   GraphDriver = DETECT;         /* Request auto-detection    */
  183.   initgraph( &GraphDriver, &GraphMode, FONT_PATH );
  184.   ErrorCode = graphresult();        /* Read result of initialization*/
  185.   if( ErrorCode != grOk )
  186.   {                    /* Error occured during init    */
  187.     printf(" Graphics System Error: %s\n", grapherrormsg( ErrorCode ) );
  188.     exit( 1 );
  189.   }
  190.  
  191.   getpalette( &palette );        /* Read the palette from board    */
  192.   MaxColors = getmaxcolor() + 1;    /* Read maximum number of colors*/
  193.  
  194.   MaxX = getmaxx();
  195.   MaxY = getmaxy();            /* Read size of screen        */
  196.  
  197.   getaspectratio( &xasp, &yasp );    /* read the hardware aspect    */
  198.   AspectRatio = (double)xasp / (double)yasp; /* Get correction factor    */
  199. }
  200.  
  201. /*                                    */
  202. /* Note 10 - REPORTSTATUS: Report the current configuration of the     */
  203. /*         system after the auto-detect initialization.        */
  204. /*                                    */
  205.  
  206. void ReportStatus(void)
  207. {
  208.   struct viewporttype      viewinfo;    /* Params for inquiry procedures*/
  209.   struct linesettingstype lineinfo;
  210.   struct fillsettingstype fillinfo;
  211.   struct textsettingstype textinfo;
  212.   struct palettetype      palette;
  213.  
  214.   char *driver, *mode;            /* Strings for driver and mode    */
  215.   int x, y, font;
  216.  
  217.   getviewsettings( &viewinfo );
  218.   getlinesettings( &lineinfo );
  219.   getfillsettings( &fillinfo );
  220.   gettextsettings( &textinfo );
  221.   getpalette( &palette );
  222.  
  223.   x = 10;
  224.   y = 4;
  225.  
  226.   MainWindow( "Status report after InitGraph" );
  227.   settextjustify( LEFT_TEXT, TOP_TEXT );
  228.  
  229.   driver = getdrivername();
  230.   mode = getmodename(GraphMode);    /* get current setting        */
  231.  
  232.   gprintf( &x, &y, "Graphics device    : %-20s (%d)", driver, GraphDriver );
  233.   gprintf( &x, &y, "Graphics mode      : %-20s (%d)", mode, GraphMode );
  234.   gprintf( &x, &y, "Screen resolution  : ( 0, 0, %d, %d )", getmaxx(), getmaxy() );
  235.  
  236.   gprintf( &x, &y, "Current view port  : ( %d, %d, %d, %d )",
  237.   viewinfo.left, viewinfo.top, viewinfo.right, viewinfo.bottom );
  238.   gprintf( &x, &y, "Clipping           : %s", viewinfo.clip ? "ON" : "OFF" );
  239.  
  240.   gprintf( &x, &y, "Current position   : ( %d, %d )", getx(), gety() );
  241.   gprintf( &x, &y, "Colors available   : %d", MaxColors );
  242.   gprintf( &x, &y, "Current color      : %d", getcolor() );
  243.  
  244.   gprintf( &x, &y, "Line style         : %s", LineStyles[ lineinfo.linestyle ] );
  245.   gprintf( &x, &y, "Line thickness     : %d", lineinfo.thickness );
  246.  
  247.   gprintf( &x, &y, "Current fill style : %s", FillStyles[ fillinfo.pattern ] );
  248.   gprintf( &x, &y, "Current fill color : %d", fillinfo.color );
  249.  
  250.   gprintf( &x, &y, "Current font       : %s", Fonts[ textinfo.font ] );
  251.   gprintf( &x, &y, "Text direction     : %s", TextDirect[ textinfo.direction ] );
  252.   gprintf( &x, &y, "Character size     : %d", textinfo.charsize );
  253.   gprintf( &x, &y, "Horizontal justify : %s", HorizJust[ textinfo.horiz ] );
  254.   gprintf( &x, &y, "Vertical justify   : %s", VertJust[ textinfo.vert ] );
  255.   gprintf( &x, &y, "Number of fonts    : %d", NFONTS );
  256.   for( font=DEFAULT_FONT ; font<=BOLD_FONT ; ++font )
  257.     {    /* For each available font    */
  258.     gprintf( &x, &y, "%-20s %s", (font==DEFAULT_FONT) ? "The typefaces are  :" : " ",
  259.          Fonts[font] );
  260.     }
  261.  
  262.   Pause();                /* Pause for user to read screen*/
  263.  
  264. }
  265.  
  266. /*                                    */
  267. /* Note 11 - TEXTDUMP: Display all the characters in each of the     */
  268. /*         available fonts.                        */
  269. /*                                    */
  270.  
  271. void TextDump()
  272. {
  273.   static int CGASizes[]  = { 1, 3, 7, 3, 3, 2, 2, 2, 2, 2, 2  };
  274.   static int NormSizes[] = { 1, 4, 7, 4, 4, 2, 2, 2, 2, 2, 2  };
  275.  
  276.   char buffer[80];
  277.   int font, ch, lwidth, size;
  278.   struct viewporttype vp;
  279.  
  280.   for( font=DEFAULT_FONT ; font<=BOLD_FONT ; ++font )
  281.     {    /* For each available font    */
  282.     sprintf( buffer, "%s Character Set", Fonts[font] );
  283.     MainWindow( buffer );        /* Display fontname as banner    */
  284.     getviewsettings( &vp );        /* read current viewport    */
  285.  
  286.     settextjustify( LEFT_TEXT, TOP_TEXT );
  287.     moveto( 2, 3 );           /* Starting position of first line of text */
  288.  
  289.     buffer[1] = '\0';            /* Terminate a string of one character  */
  290.  
  291.     if( font == DEFAULT_FONT )
  292.     {
  293.       changetextstyle( font, HORIZ_DIR, 1 );
  294.       ch = 0;
  295.     }
  296.     else
  297.     {
  298.       size = (MaxY < 200) ? CGASizes[font] : NormSizes[font];
  299.       changetextstyle( font, HORIZ_DIR, size );
  300.       ch = '!';                         /* Begin at 1st printable       */
  301.     }
  302.     while( ch < 256 )
  303.     {                                /* For each possible character    */
  304.       buffer[0] = ch;                 /* Put character into a string    */
  305.       lwidth = textwidth (buffer);      /* Width of this character      */
  306.       if( (getx() + lwidth) > vp.right )
  307.     /* This line is filled so start a new line of text */
  308.     moveto( 2, gety() + textheight("H") + 3 );
  309.       outtext( buffer );        /* send string to screen    */
  310.       ++ch;                /* Do the next character    */
  311.     }
  312.  
  313.     Pause();                /* Pause until user acks    */
  314.  
  315.   }                    /* End of FONT loop        */
  316.  
  317. }
  318.  
  319. /*                                    */
  320. /* Note 12 - RANDOMBARS: Display random bars                 */
  321. /*                                    */
  322.  
  323. void RandomBars(void)
  324. {
  325.   int color;
  326.  
  327.   MainWindow( "Random Bars" );
  328.   StatusLine( "Esc aborts or press a key..." ); /* Put msg at bottom of screen   */
  329.   while( !kbhit() )
  330.   {            /* Until user enters a key...    */
  331.     color = random( MaxColors-1 )+1;
  332.     setcolor( color );
  333.     setfillstyle( random(11)+1, color );
  334.     bar3d( random( getmaxx() ), random( getmaxy() ),
  335.        random( getmaxx() ), random( getmaxy() ), 0, OFF);
  336.   }
  337.  
  338.   Pause();                /* Pause for user's response    */
  339.  
  340. }
  341.  
  342.  
  343. /*                                    */
  344. /* Note 13 - TEXTDEMO: Show each font to the user in several sizes.    */
  345. /*                                    */
  346.  
  347. void TextDemo(void)
  348. {
  349.   int charsize[] = { 1, 3, 7, 3, 4, 2, 2, 2, 2, 2, 2   };
  350.   int font, size;
  351.   int h, x, y, i;
  352.   struct viewporttype vp;
  353.   char buffer[80];
  354.  
  355.   for( font=DEFAULT_FONT ; font<=BOLD_FONT ; ++font )
  356.   {    /* For each of the available fonts    */
  357.  
  358.     sprintf( buffer, "%s Font Demonstration", Fonts[font] );
  359.     MainWindow( buffer );
  360.     getviewsettings( &vp );
  361.  
  362.     changetextstyle( font, VERT_DIR, charsize[font] );
  363.     settextjustify( CENTER_TEXT, BOTTOM_TEXT );
  364.     outtextxy( 2*textwidth("M"), vp.bottom - 2*textheight("M"), "Vertical" );
  365.  
  366.     changetextstyle( font, HORIZ_DIR, charsize[font] );
  367.     settextjustify( LEFT_TEXT, TOP_TEXT );
  368.     outtextxy( 2*textwidth("M"), 2, "Horizontal" );
  369.  
  370.     settextjustify( CENTER_TEXT, CENTER_TEXT );
  371.     x = (vp.right - vp.left) / 2;
  372.     y = textheight( "H" );
  373.  
  374.     for( i=1 ; i<5 ; ++i )
  375.     {        /* For each of the sizes */
  376.       size = (font == SMALL_FONT) ? i+3 : i;
  377.       changetextstyle( font, HORIZ_DIR, size );
  378.       h = textheight( "H" );
  379.       y += h;
  380.       sprintf( buffer, "Size %d", size );
  381.       outtextxy( x, y, buffer );
  382.  
  383.     }  /* for i */
  384.  
  385.     y += h / 2;            /* Move down the screen     */
  386.     settextjustify( CENTER_TEXT, TOP_TEXT );
  387.     setusercharsize( 2, 1, 1, 1 );
  388.     changetextstyle( font, HORIZ_DIR, USER_CHAR_SIZE );
  389.     outtextxy( (vp.right-vp.left)/2, y, "User Defined Size" );
  390.  
  391.     Pause();                /* Pause to let user look    */
  392.  
  393.   }                    /* End of FONT loop        */
  394.  
  395. }
  396.  
  397. /*                                    */
  398. /* Note 14 - COLORDEMO: Display the current color palette on the screen.*/
  399. /*                                    */
  400.  
  401. void ColorDemo(void)
  402. {
  403.   struct viewporttype vp;
  404.   int color, height, width;
  405.   int x, y, i, j;
  406.   char cnum[5];
  407.  
  408.   MainWindow( "Color Demonstration" );  /* Show demonstration name      */
  409.  
  410.   color = 1;
  411.   getviewsettings( &vp );        /* Get the current window size    */
  412.   width  = 2 * ( (vp.right+1) / 16 );       /* Get box dimensions       */
  413.   height = 2 * ( (vp.bottom-10) / 10 );
  414.  
  415.   x = width / 2;
  416.   y = height / 2;    /* Leave 1/2 box border     */
  417.  
  418.   for( j=0 ; j<3 ; ++j )
  419.   {        /* Row loop            */
  420.  
  421.     for( i=0 ; i<5 ; ++i )
  422.     {        /* Column loop            */
  423.  
  424.       setfillstyle(SOLID_FILL, color);    /* Set to solid fill in color    */
  425.       setcolor( color );        /* Set the same border color    */
  426.  
  427.       bar( x, y, x+width, y+height );    /* Draw the rectangle        */
  428.  
  429.       if( color == BLACK )
  430.       {        /* If box was black...        */
  431.     setcolor( WHITE );        /* Set drawing color to white    */
  432.     rectangle( x, y, x+width, y+height );  /* Outline black in white*/
  433.       }
  434.  
  435.       itoa( color, cnum, 10 );        /* Convert # to ASCII        */
  436.       outtextxy( x+(width/2), y+height+4, cnum );  /* Show color #    */
  437.  
  438.       color = ++color % MaxColors;    /* Advance to the next color    */
  439.       x += (width / 2) * 3;        /* move the column base     */
  440.     }                /* End of Column loop        */
  441.  
  442.     y += (height / 2) * 3;        /* move the row base        */
  443.     x = width / 2;            /* reset column base        */
  444.   }                    /* End of Row loop        */
  445.  
  446.   Pause();                /* Pause for user's response    */
  447.  
  448. }
  449.  
  450. /*                                    */
  451. /* Note 15 - ARCDEMO: Display a random pattern of arcs on the screen    */
  452. /*         until the user says enough.                */
  453. /*                                    */
  454.  
  455. void ArcDemo(void)
  456. {
  457.   int mradius;                /* Maximum radius allowed    */
  458.   int eangle;                /* Random end angle of Arc    */
  459.   struct arccoordstype ai;        /* Used to read Arc coord info    */
  460.  
  461.   MainWindow( "Arc Demonstration" );
  462.   StatusLine( "ESC Aborts - Press a Key to stop" );
  463.  
  464.   mradius = MaxY / 10;            /* Determine the maximum radius */
  465.  
  466.   while( !kbhit() )
  467.   {            /* Repeat until a key is hit    */
  468.     setcolor( random( MaxColors - 1 ) + 1 );    /* Randomly select a color    */
  469.     eangle = random( 358 ) + 1;     /* Select an end angle        */
  470.     arc( random(MaxX), random(MaxY), random(eangle), eangle, mradius );
  471.     getarccoords( &ai );        /* Read arc coord data        */
  472.     line( ai.x, ai.y, ai.xstart, ai.ystart ); /* line from start to center */
  473.     line( ai.x, ai.y,    ai.xend,   ai.yend ); /* line from end to center   */
  474.   }                    /* End of WHILE not KBHIT    */
  475.  
  476.   Pause();                /* Wait for user's response     */
  477.  
  478. }
  479.  
  480. /*                                    */
  481. /* Note 16 - CIRCLEDEMO: Display a random pattern of circles on the    */
  482. /*         screen until the user says enough.                */
  483. /*                                    */
  484.  
  485. void CircleDemo(void)
  486. {
  487.   int mradius;                /* Maximum radius allowed    */
  488.  
  489.   MainWindow( "Circle Demonstration" );
  490.   StatusLine( "ESC Aborts - Press a Key to stop" );
  491.  
  492.   mradius = MaxY / 10;            /* Determine the maximum radius */
  493.  
  494.   while( !kbhit() )
  495.   {            /* Repeat until a key is hit    */
  496.     setcolor( random( MaxColors - 1 ) + 1 );    /* Randomly select a color    */
  497.     circle( random(MaxX), random(MaxY), random(mradius) );
  498.   }                    /* End of WHILE not KBHIT    */
  499.  
  500.   Pause();                /* Wait for user's response     */
  501.  
  502. }
  503.  
  504. /*                                    */
  505. /* Note 17 - PIEDEMO: Display a pie chart on the screen.        */
  506. /*                                    */
  507.  
  508. #define adjasp( y )    ((int)(AspectRatio * (double)(y)))
  509.  
  510. void PieDemo(void)
  511. {
  512.   struct viewporttype vp;
  513.   int xcenter, ycenter, radius, lradius;
  514.   int x, y;
  515.   double radians, piesize;
  516.  
  517.   MainWindow( "Pie Chart Demonstration" );
  518.  
  519.   getviewsettings( &vp );        /* Get the current viewport    */
  520.   xcenter = (vp.right - vp.left) / 2;    /* Center the Pie horizontally    */
  521.   ycenter = (vp.bottom - vp.top) / 2+20;/* Center the Pie vertically    */
  522.   radius  = (vp.bottom - vp.top) / 3;    /* It will cover 2/3rds screen    */
  523.   piesize = (vp.bottom - vp.top) / 4.0; /* Optimum height ratio of pie    */
  524.  
  525.   while( (AspectRatio*radius) < piesize ) ++radius;
  526.  
  527.   lradius = radius + ( radius / 5 );    /* Labels placed 20% farther    */
  528.  
  529.   changetextstyle( TRIPLEX_FONT, HORIZ_DIR, 4 );
  530.   settextjustify( CENTER_TEXT, TOP_TEXT );
  531.   outtextxy( MaxX/2, 6, "A Sample Pie Chart" );
  532.   changetextstyle( TRIPLEX_FONT, HORIZ_DIR, 1 );
  533.   settextjustify( CENTER_TEXT, TOP_TEXT );
  534.  
  535.   setfillstyle( SOLID_FILL, RED );
  536.   pieslice( xcenter+10, ycenter-adjasp(10), 0, 90, radius );
  537.   radians = torad( 45 );
  538.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  539.   y = ycenter - (int)( sin( radians ) * (double)lradius * AspectRatio );
  540.   settextjustify( LEFT_TEXT, BOTTOM_TEXT );
  541.   outtextxy( x, y, "25 %" );
  542.  
  543.   setfillstyle( WIDE_DOT_FILL, GREEN );
  544.   pieslice( xcenter, ycenter, 90, 135, radius );
  545.   radians = torad( 113 );
  546.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  547.   y = ycenter - (int)( sin( radians ) * (double)lradius * AspectRatio );
  548.   settextjustify( RIGHT_TEXT, BOTTOM_TEXT );
  549.   outtextxy( x, y, "12.5 %" );
  550.  
  551.   setfillstyle( INTERLEAVE_FILL, YELLOW );
  552.   settextjustify( RIGHT_TEXT, CENTER_TEXT );
  553.   pieslice( xcenter-10, ycenter, 135, 225, radius );
  554.   radians = torad( 180 );
  555.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  556.   y = ycenter - (int)( sin( radians ) * (double)lradius * AspectRatio );
  557.   settextjustify( RIGHT_TEXT, CENTER_TEXT );
  558.   outtextxy( x, y, "25 %" );
  559.  
  560.   setfillstyle( HATCH_FILL, BLUE );
  561.   pieslice( xcenter, ycenter, 225, 360, radius );
  562.   radians = torad( 293 );
  563.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  564.   y = ycenter - (int)( sin( radians ) * (double)lradius * AspectRatio );
  565.   settextjustify( LEFT_TEXT, TOP_TEXT );
  566.   outtextxy( x, y, "37.5 %" );
  567.  
  568.   Pause();                /* Pause for user's response    */
  569.  
  570. }
  571.  
  572. /*                                    */
  573. /* Note 18 - BARDEMO: Draw a 2-D bar chart using Bar and Rectangle.    */
  574. /*                                    */
  575.  
  576. void BarDemo(void)
  577. {
  578.   int barheight[] = { 1, 3, 5, 2, 4   };
  579.   int styles[]      = { 1, 3, 10, 5, 9, 1    };
  580.   int xstep, ystep;
  581.   int sheight, swidth;
  582.   int i, j, h;
  583.   struct viewporttype vp;
  584.   char buffer[40];
  585.  
  586.   MainWindow( "Bar / Rectangle Demonstration" );
  587.   h = 3 * textheight( "H" );
  588.   getviewsettings( &vp );
  589.   settextjustify( CENTER_TEXT, TOP_TEXT );
  590.   changetextstyle( TRIPLEX_FONT, HORIZ_DIR, 4 );
  591.   outtextxy( MaxX /2, 6, "These are 2-D Bars" );
  592.   changetextstyle( DEFAULT_FONT, HORIZ_DIR, 1 );
  593.   setviewport( vp.left+50, vp.top+30, vp.right-50, vp.bottom-10, 1 );
  594.  
  595.   getviewsettings( &vp );
  596.   sheight = vp.bottom - vp.top;
  597.   swidth  = vp.right  - vp.left;
  598.  
  599.   line( h, h, h, sheight-h );
  600.   line( h, sheight-h, sheight-h, sheight-h );
  601.   ystep = (sheight - (2*h) ) / 5;
  602.   xstep = (swidth  - (2*h) ) / 5;
  603.   j = sheight - h;
  604.   settextjustify( CENTER_TEXT, CENTER_TEXT );
  605.  
  606.   for( i=0 ; i<6 ; ++i )
  607.   {
  608.     line( h/2, j, h, j );
  609.     itoa( i, buffer, 10 );
  610.     outtextxy( 0, j, buffer );
  611.     j -= ystep;
  612.   }
  613.  
  614.   j = h;
  615.   settextjustify( CENTER_TEXT, TOP_TEXT );
  616.   for( i=0 ; i<6 ; ++i )
  617.   {
  618.     setfillstyle( styles[i], random(MaxColors) );
  619.     line( j, sheight - h, j, sheight- 3 - (h/2) );
  620.     itoa( i, buffer, 10 );
  621.     outtextxy( j, sheight - (h/2), buffer );
  622.     if( i != 5 )
  623.     {
  624.       bar( j, (sheight-h)-(barheight[i] * ystep), j+xstep, sheight-h-1 );
  625.       rectangle( j, (sheight-h)-(barheight[i] * ystep), j+xstep, sheight-h);
  626.     }
  627.     j += xstep;
  628.   }
  629.  
  630.   Pause();
  631.  
  632. }
  633.  
  634. /*                                    */
  635. /*    PUTPIXELDEMO: Display a pattern of random dots on the screen    */
  636. /*    and pick them back up again.                    */
  637. /*                                    */
  638.  
  639. void PutPixelDemo(void)
  640. {
  641.   int seed = 1958;
  642.   int i, x, y, h, w, color;
  643.   struct viewporttype vp;
  644.  
  645.   MainWindow( "PutPixel / GetPixel Demonstration" );
  646.  
  647.   getviewsettings( &vp );
  648.   h = vp.bottom - vp.top;
  649.   w = vp.right    - vp.left;
  650.  
  651.   srand( seed );            /* Restart random # function    */
  652.  
  653.   for( i=0 ; i<5000 ; ++i )
  654.   {        /* Put 5000 pixels on screen    */
  655.     x = 1 + random( w - 1 );        /* Generate a random location    */
  656.     y = 1 + random( h - 1 );
  657.     color = random( MaxColors );
  658.     putpixel( x, y, color );
  659.   }
  660.  
  661.   srand( seed );            /* Restart Random # at same #    */
  662.  
  663.   for( i=0 ; i<5000 ; ++i )
  664.   {        /* Take the 5000 pixels off    */
  665.     x = 1 + random( w - 1 );        /* Generate a random location    */
  666.     y = 1 + random( h - 1 );
  667.     color = getpixel( x, y );        /* Read the color pixel     */
  668.     if( color == random( MaxColors ) )    /* Used to keep RANDOM in sync    */
  669.       putpixel( x, y, 0 );        /* Write pixel to BLACK     */
  670.   }
  671.  
  672.   Pause();                /* Wait for user's response     */
  673.  
  674. }
  675.  
  676. /*                                    */
  677. /*   PUTIMAGEDEMO                            */
  678. /*                                    */
  679. void PutImageDemo(void)
  680. {
  681.   static int r        = 20;
  682.   static int StartX = 100;
  683.   static int StartY = 50;
  684.  
  685.   struct viewporttype vp;
  686.   int PauseTime, x, y, ulx, uly, lrx, lry, size, i, width, height, step;
  687.   void *Saucer;
  688.  
  689.   MainWindow("GetImage / PutImage Demonstration");
  690.   getviewsettings( &vp );
  691.  
  692.   /* Draw Saucer */
  693.   setfillstyle( SOLID_FILL, getmaxcolor() );
  694.   fillellipse(StartX, StartY, r, (r/3)+2);
  695.   ellipse(StartX, StartY-4, 190, 357, r, r/3);
  696.  
  697.   line(StartX+7, StartY-6, StartX+10, StartY-12);
  698.   circle(StartX+10, StartY-12, 2);
  699.   line(StartX-7, StartY-6, StartX-10, StartY-12);
  700.   circle(StartX-10, StartY-12, 2);
  701.  
  702.  
  703.   /* Read saucer image */
  704.   ulx = StartX-(r+1);
  705.   uly = StartY-14;
  706.   lrx = StartX+(r+1);
  707.   lry = StartY+(r/3)+3;
  708.   width = lrx - ulx + 1;
  709.   height = lry - uly + 1;
  710.   size = imagesize(ulx, uly, lrx, lry);
  711.  
  712.   Saucer = malloc( size );
  713.   getimage(ulx, uly, lrx, lry, Saucer);
  714.   putimage(ulx, uly, Saucer, XOR_PUT);
  715.  
  716. /* Plot some "stars"  */
  717.   for ( i=0 ; i<1000; ++i )
  718.     putpixel(random(MaxX), random(MaxY), random( MaxColors-1 )+1);
  719.   x = MaxX / 2;
  720.   y = MaxY / 2;
  721.   PauseTime = 70;
  722.   StatusLine ( "Esc aborts or press a key..." );
  723.  
  724.   /* until a key is hit */
  725.   while ( !kbhit() )
  726.   {
  727.     /* Draw the Saucer */
  728.     putimage(x, y, Saucer, XOR_PUT);             /*  draw image  */
  729.     delay(PauseTime);
  730.     putimage(x, y, Saucer, XOR_PUT);             /* erase image  */
  731.  
  732.     /* Move Saucer */
  733.  
  734.     step = random( 2*r );
  735.     if ((step/2) % 2 != 0 )
  736.       step = -1 * step;
  737.     x = x + step;
  738.     step = random( r );
  739.     if ((step/2) % 2 != 0 )
  740.       step = -1 * step;
  741.     y = y + step;
  742.  
  743.     if (vp.left + x + width - 1 > vp.right)
  744.       x = vp.right-vp.left-width + 1;
  745.     else
  746.       if (x < 0)
  747.     x = 0;
  748.     if (vp.top + y + height - 1 > vp.bottom)
  749.       y = vp.bottom-vp.top-height + 1;
  750.     else
  751.       if (y < 0)
  752.     y = 0;
  753.   }
  754.   free( Saucer );
  755.   Pause();
  756. }
  757.  
  758.  
  759. /*                                    */
  760. /*    LINETODEMO: Display a pattern using moveto and lineto commands. */
  761. /*                                    */
  762.  
  763. #define MAXPTS    15
  764.  
  765. void LineToDemo(void)
  766. {
  767.   struct viewporttype vp;
  768.   struct PTS points[MAXPTS];
  769.   int i, j, h, w, xcenter, ycenter;
  770.   int radius, angle, step;
  771.   double  rads;
  772.  
  773.   MainWindow( "MoveTo / LineTo Demonstration" );
  774.  
  775.   getviewsettings( &vp );
  776.   h = vp.bottom - vp.top;
  777.   w = vp.right    - vp.left;
  778.  
  779.   xcenter = w / 2;            /* Determine the center of circle */
  780.   ycenter = h / 2;
  781.   radius  = (h - 30) / (AspectRatio * 2);
  782.   step      = 360 / MAXPTS;        /* Determine # of increments    */
  783.  
  784.   angle = 0;                /* Begin at zero degrees    */
  785.   for( i=0 ; i<MAXPTS ; ++i )
  786.   {        /* Determine circle intercepts    */
  787.     rads = (double)angle * PI / 180.0;    /* Convert angle to radians    */
  788.     points[i].x = xcenter + (int)( cos(rads) * radius );
  789.     points[i].y = ycenter - (int)( sin(rads) * radius * AspectRatio );
  790.     angle += step;            /* Move to next increment    */
  791.   }
  792.  
  793.   circle( xcenter, ycenter, radius );    /* Draw bounding circle     */
  794.  
  795.   for( i=0 ; i<MAXPTS ; ++i )
  796.   {        /* Draw the chords to the circle */
  797.     for( j=i ; j<MAXPTS ; ++j )
  798.     {    /* For each remaining intersect */
  799.       moveto(points[i].x, points[i].y); /* Move to beginning of chord    */
  800.       lineto(points[j].x, points[j].y); /* Draw the chord        */
  801.     }
  802.   }
  803.  
  804.   Pause();                /* Wait for user's response     */
  805.  
  806. }
  807.  
  808. /*                                    */
  809. /*    CRTMODEDEMO: Demonstrate the effects of the change mode     */
  810. /*    commands on the current screen.                 */
  811. /*                                    */
  812.  
  813. void CRTModeDemo(void)
  814. {
  815.   struct viewporttype vp;
  816.   int mode;
  817.  
  818.   MainWindow( "SetGraphMode / RestoreCRTMode demo" );
  819.   getviewsettings( &vp );
  820.   mode = getgraphmode();
  821.   settextjustify( CENTER_TEXT, CENTER_TEXT );
  822.  
  823.   outtextxy( (vp.right-vp.left)/2, (vp.bottom-vp.top)/2,
  824.          "Now you are in graphics mode..." );
  825.   StatusLine( "Press any key for text mode..." );
  826.   getch();
  827.  
  828.   restorecrtmode();
  829.   printf( "Now you are in text mode.\n\n" );
  830.   printf( "Press any key to go back to graphics..." );
  831.   getch();
  832.  
  833.   setgraphmode( mode );
  834.   MainWindow( "SetGraphMode / RestoreCRTMode demo" );
  835.   settextjustify( CENTER_TEXT, CENTER_TEXT );
  836.   outtextxy( (vp.right-vp.left)/2, (vp.bottom-vp.top)/2,
  837.   "Back in Graphics Mode..." );
  838.  
  839.   Pause();                /* Wait for user's response     */
  840.  
  841. }
  842.  
  843. /*                                    */
  844. /*    USERLINESTYLEDEMO: Display line styles showing the user     */
  845. /*    defined line style functions.                    */
  846. /*                                    */
  847.  
  848. void UserLineStyleDemo(void)
  849. {
  850.   int x, y, i, h, flag;
  851.   unsigned int style;
  852.   struct viewporttype vp;
  853.  
  854.   MainWindow( "User defined line styles" );
  855.  
  856.   getviewsettings( &vp );
  857.   h = vp.bottom - vp.top;
  858.  
  859.   x = 4;
  860.   y = 10;
  861.   style = 0;
  862.   i = 0;
  863.  
  864.   settextjustify( CENTER_TEXT, TOP_TEXT );
  865.   flag = TRUE;                /* Set the bits in this pass    */
  866.  
  867.   while( x < vp.right-2 )
  868.   {        /* Draw lines across the screen */
  869.  
  870.     if( flag )                /* If flag, set bits...     */
  871.       style = style | (1 << i);     /*    Set the Ith bit in word    */
  872.     else                /* If no flag, clear bits    */
  873.     style = style & !(0x8000 >> i);    /*    Clear the Ith bit in word */
  874.  
  875.     setlinestyle( USERBIT_LINE, style, NORM_WIDTH );
  876.     line( x, y, x, h-y );        /* Draw the new line pattern    */
  877.  
  878.     x += 5;                /* Move the X location of line    */
  879.     i = ++i % 16;            /* Advance to next bit pattern    */
  880.  
  881.     if( style == 0xffff )
  882.     {        /* Are all bits set?        */
  883.       flag = FALSE;            /*   begin removing bits    */
  884.       i = 0;                /* Start with whole pattern    */
  885.     }
  886.     else
  887.     {                /* Bits not all set...        */
  888.       if( style == 0 )            /* Are all bits clear?        */
  889.     flag = TRUE;            /*   begin setting bits     */
  890.     }
  891.   }
  892.  
  893.   settextjustify( LEFT_TEXT, TOP_TEXT );
  894.  
  895.   Pause();                /* Wait for user's response     */
  896.  
  897. }
  898.  
  899. /*                                    */
  900. /* Note 19 - FILLSTYLEDEMO: Display with various user-defined fill      */
  901. /*         patterns.                            */
  902. /*                                    */
  903.  
  904. void FillStyleDemo(void)
  905. {
  906.   int h, w, style;
  907.   int i, j, x, y;
  908.   struct viewporttype vp;
  909.   char buffer[40];
  910.  
  911.   MainWindow( "Pre-defined Fill Styles" );
  912.  
  913.   getviewsettings( &vp );
  914.   w = 2 * ((vp.right  +  1) / 13);
  915.   h = 2 * ((vp.bottom - 10) / 10);
  916.  
  917.   x = w / 2;
  918.   y = h / 2;        /* Leave 1/2 blk margin     */
  919.   style = 0;
  920.  
  921.   for( j=0 ; j<3 ; ++j )
  922.   {        /* Three rows of boxes        */
  923.     for( i=0 ; i<4 ; ++i )
  924.     {        /* Four column of boxes     */
  925.       setfillstyle(style, MaxColors-1); /* Set the fill style and WHITE */
  926.       bar( x, y, x+w, y+h );        /* Draw the actual box        */
  927.       rectangle( x, y, x+w, y+h );    /* Outline the box        */
  928.       itoa( style, buffer, 10 );    /* Convert style 3 to ASCII    */
  929.       outtextxy( x+(w / 2), y+h+4, buffer );
  930.       ++style;                /* Go on to next style #    */
  931.       x += (w / 2) * 3;         /* Go to next column        */
  932.     }                /* End of coulmn loop        */
  933.     x = w / 2;                /* Put base back to 1st column    */
  934.     y += (h / 2) * 3;            /* Advance to next row        */
  935.   }                    /* End of Row loop        */
  936.  
  937.   settextjustify( LEFT_TEXT, TOP_TEXT );
  938.  
  939.   Pause();                /* Wait for user's response     */
  940.  
  941. }
  942.  
  943. /*                                    */
  944. /* Note 20 - PALETTEDEMO: Display a pattern of rectangles on the screen    */
  945. /*         and change palette colors until the user says enough.    */
  946. /*                                    */
  947.  
  948. void PaletteDemo(void)
  949. {
  950.   int i, j, x, y, color;
  951.   struct viewporttype vp;
  952.   int height, width;
  953.  
  954.   MainWindow( "Palette Demonstration" );
  955.   StatusLine( "Press any key to continue, ESC to Abort" );
  956.  
  957.   getviewsettings( &vp );
  958.   width  = (vp.right - vp.left) / 15;    /* get width of the box     */
  959.   height = (vp.bottom - vp.top) / 10;    /* Get the height of the box    */
  960.  
  961.   x = y = 0;                /* Start in upper corner    */
  962.   color = 1;                /* Begin at 1st color        */
  963.  
  964.   for( j=0 ; j<10 ; ++j )
  965.   {        /* For 10 rows of boxes     */
  966.     for( i=0 ; i<15 ; ++i )
  967.     {        /* For 15 columns of boxes    */
  968.       setfillstyle( SOLID_FILL, color++ );    /* Set the color of box */
  969.       bar( x, y, x+width, y+height );        /* Draw the box     */
  970.       x += width + 1;                /* Advance to next col    */
  971.       color = 1 + (color % (MaxColors - 2));    /* Set new color    */
  972.     }                /* End of COLUMN loop        */
  973.     x = 0;                /* Goto 1st column        */
  974.     y += height + 1;            /* Goto next row        */
  975.   }                    /* End of ROW loop        */
  976.  
  977.   while( !kbhit() )
  978.   {            /* Until user enters a key...    */
  979.     setpalette( 1+random(MaxColors - 2), random( 65 ) );
  980.   }
  981.  
  982.   setallpalette( &palette );
  983.  
  984.   Pause();                /* Wait for user's response     */
  985.  
  986. }
  987.  
  988. /*                                    */
  989. /*    POLYDEMO: Display a random pattern of polygons on the screen    */
  990. /*    until the user says enough.                    */
  991. /*                                    */
  992.  
  993. #define MaxPts        6        /* Maximum # of pts in polygon    */
  994.  
  995. void PolyDemo(void)
  996. {
  997.   struct PTS poly[ MaxPts ];        /* Space to hold datapoints    */
  998.   int color;                /* Current drawing color    */
  999.   int i;
  1000.  
  1001.   MainWindow( "DrawPoly / FillPoly Demonstration" );
  1002.   StatusLine( "ESC Aborts - Press a Key to stop" );
  1003.  
  1004.   while( !kbhit() )
  1005.   {            /* Repeat until a key is hit    */
  1006.  
  1007.     color = 1 + random( MaxColors-1 );    /* Get a random color # (no blk)*/
  1008.     setfillstyle( random(10), color );    /* Set a random line style    */
  1009.     setcolor( color );            /* Set the desired color    */
  1010.  
  1011.     for( i=0 ; i<(MaxPts-1) ; i++ )
  1012.     {    /* Determine a random polygon    */
  1013.       poly[i].x = random( MaxX );    /* Set the x coord of point    */
  1014.       poly[i].y = random( MaxY );    /* Set the y coord of point    */
  1015.     }
  1016.  
  1017.     poly[i].x = poly[0].x;        /* last point = first point    */
  1018.     poly[i].y = poly[1].y;
  1019.  
  1020.     fillpoly( MaxPts, (int far *)poly );    /* Draw the actual polygon        */
  1021.   }                    /* End of WHILE not KBHIT    */
  1022.  
  1023.   Pause();                /* Wait for user's response     */
  1024.  
  1025. }
  1026.  
  1027.  
  1028. /*                                    */
  1029. /*    SAYGOODBYE: Give a closing screen to the user before leaving.    */
  1030. /*                                    */
  1031.  
  1032. void SayGoodbye(void)
  1033. {
  1034.   struct viewporttype viewinfo;     /* Structure to read viewport    */
  1035.   int h, w;
  1036.  
  1037.   MainWindow( "== Finale ==" );
  1038.  
  1039.   getviewsettings( &viewinfo );     /* Read viewport settings    */
  1040.   changetextstyle( TRIPLEX_FONT, HORIZ_DIR, 4 );
  1041.   settextjustify( CENTER_TEXT, CENTER_TEXT );
  1042.  
  1043.   h = viewinfo.bottom - viewinfo.top;
  1044.   w = viewinfo.right  - viewinfo.left;
  1045.   outtextxy( w/2, h/2, "That's all, folks!" );
  1046.  
  1047.   StatusLine( "Press any key to EXIT" );
  1048.   getch();
  1049.  
  1050.   cleardevice();            /* Clear the graphics screen    */
  1051.  
  1052. }
  1053.  
  1054. /*                                    */
  1055. /*    PAUSE: Pause until the user enters a keystroke. If the        */
  1056. /*    key is an ESC, then exit program, else simply return.        */
  1057. /*                                    */
  1058.  
  1059. void Pause(void)
  1060. {
  1061.   static char msg[] = "Esc aborts or press a key...";
  1062.   int c;
  1063.  
  1064.   StatusLine( msg );            /* Put msg at bottom of screen    */
  1065.  
  1066.   c = getch();                /* Read a character from kbd    */
  1067.  
  1068.   if( ESC == c )
  1069.   {            /* Does user wish to leave?    */
  1070.     closegraph();            /* Change to text mode        */
  1071.     exit( 1 );                /* Return to OS         */
  1072.   }
  1073.  
  1074.   if( c == 0 )
  1075.   {             /* Did use hit a non-ASCII key? */
  1076.     c = getch();            /* Read scan code for keyboard    */
  1077.   }
  1078.  
  1079.   cleardevice();            /* Clear the screen        */
  1080.  
  1081. }
  1082.  
  1083. /*                                    */
  1084. /*    MAINWINDOW: Establish the main window for the demo and set    */
  1085. /*    a viewport for the demo code.                    */
  1086. /*                                    */
  1087.  
  1088. void MainWindow( char *header )
  1089. {
  1090.   int height;
  1091.  
  1092.   cleardevice();            /* Clear graphics screen    */
  1093.   setcolor( MaxColors - 1 );        /* Set current color to white    */
  1094.   setviewport( 0, 0, MaxX, MaxY, 1 );    /* Open port to full screen    */
  1095.  
  1096.   height = textheight( "H" );           /* Get basic text height        */
  1097.  
  1098.   changetextstyle( DEFAULT_FONT, HORIZ_DIR, 1 );
  1099.   settextjustify( CENTER_TEXT, TOP_TEXT );
  1100.   outtextxy( MaxX/2, 2, header );
  1101.   setviewport( 0, height+4, MaxX, MaxY-(height+4), 1 );
  1102.   DrawBorder();
  1103.   setviewport( 1, height+5, MaxX-1, MaxY-(height+5), 1 );
  1104.  
  1105. }
  1106.  
  1107. /*                                    */
  1108. /*    STATUSLINE: Display a status line at the bottom of the screen.    */
  1109. /*                                    */
  1110.  
  1111. void StatusLine( char *msg )
  1112. {
  1113.   int height;
  1114.  
  1115.   setviewport( 0, 0, MaxX, MaxY, 1 );    /* Open port to full screen    */
  1116.   setcolor( MaxColors - 1 );        /* Set current color to white    */
  1117.  
  1118.   changetextstyle( DEFAULT_FONT, HORIZ_DIR, 1 );
  1119.   settextjustify( CENTER_TEXT, TOP_TEXT );
  1120.   setlinestyle( SOLID_LINE, 0, NORM_WIDTH );
  1121.   setfillstyle( EMPTY_FILL, 0 );
  1122.  
  1123.   height = textheight( "H" );           /* Detemine current height      */
  1124.   bar( 0, MaxY-(height+4), MaxX, MaxY );
  1125.   rectangle( 0, MaxY-(height+4), MaxX, MaxY );
  1126.   outtextxy( MaxX/2, MaxY-(height+2), msg );
  1127.   setviewport( 1, height+5, MaxX-1, MaxY-(height+5), 1 );
  1128.  
  1129. }
  1130.  
  1131. /*                                    */
  1132. /*    DRAWBORDER: Draw a solid single line around the current     */
  1133. /*    viewport.                            */
  1134. /*                                    */
  1135.  
  1136. void DrawBorder(void)
  1137. {
  1138.   struct viewporttype vp;
  1139.  
  1140.   setcolor( MaxColors - 1 );        /* Set current color to white    */
  1141.  
  1142.   setlinestyle( SOLID_LINE, 0, NORM_WIDTH );
  1143.  
  1144.   getviewsettings( &vp );
  1145.   rectangle( 0, 0, vp.right-vp.left, vp.bottom-vp.top );
  1146.  
  1147. }
  1148.  
  1149. /*                                    */
  1150. /* Note 21 - CHANGETEXTSTYLE: similar to Borland C++ settextstyle, but     */
  1151. /*         checks forerrors that might occur while loading the font     */
  1152. /*         file.                            */
  1153. /*                                    */
  1154.  
  1155. void changetextstyle(int font, int direction, int charsize)
  1156. {
  1157.   int ErrorCode;
  1158.   /* Inserted for debugging */
  1159.   struct textsettingstype texttypeinfo;
  1160.  
  1161.   graphresult();            /* clear error code        */
  1162.   settextstyle(font, direction, charsize);
  1163.   gettextsettings (&texttypeinfo);
  1164.   ErrorCode = graphresult();        /* check result         */
  1165.   if( ErrorCode != grOk )
  1166.   {        /* if error occured        */
  1167.     closegraph();
  1168.     printf(" Graphics System Error: %s\n", grapherrormsg( ErrorCode ) );
  1169.     exit( 1 );
  1170.   }
  1171. }
  1172.  
  1173. /*                                    */
  1174. /*    GPRINTF: Used like PRINTF except the output is sent to the    */
  1175. /*    screen in graphics mode at the specified co-ordinate.        */
  1176. /*                                    */
  1177.  
  1178. int gprintf( int *xloc, int *yloc, char *fmt, ... )
  1179. {
  1180.   va_list  argptr;            /* Argument list pointer    */
  1181.   char str[140];            /* Buffer to build sting into    */
  1182.   int cnt;                /* Result of SPRINTF for return */
  1183.  
  1184.   va_start( argptr, fmt );        /* Initialize va_ functions    */
  1185.  
  1186.   cnt = vsprintf( str, fmt, argptr );    /* prints string to buffer    */
  1187.   outtextxy( *xloc, *yloc, str );    /* Send string in graphics mode */
  1188.   *yloc += textheight( "H" ) + 2;       /* Advance to next line         */
  1189.  
  1190.   va_end( argptr );            /* Close va_ functions        */
  1191.  
  1192.   return( cnt );            /* Return the conversion count    */
  1193.  
  1194. }
  1195.